﻿#ifndef LK_WINDOWS_WAS_SOUNDENVIRONMENT_//由W意波(LuoJun)编写
#define LK_WINDOWS_WAS_SOUNDENVIRONMENT_
namespace LK
{
	namespace Windows
	{
		namespace WAS
		{
			//各种GUID和静态常量

			const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
			const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
			const IID IID_IAudioClient = __uuidof(IAudioClient);
			const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
			const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);

			/**
			@brief 音频环境对象，负责音频环境的初始化*/
			class SoundEnvironment
			{
				friend class Speaker;
				friend class Recorder;
				friend class DeviceChangeCallback;
				//线程同步控制
				static Mutex soundtc;
				//录音设备集合
				static IMMDeviceCollection* pRecordingDevices;
				//播放设备集合
				static IMMDeviceCollection* pSpeakingDevices;
				//设备枚举器
				static IMMDeviceEnumerator *pEnumerator;
				//产生异步的设备更改过程
				static DeviceChangeCallback* pNotify;
				//记录已有的扬声器，以便环境变化时发出通知
				static LK::Collection::DefaultArray<Speaker*> speakerList;
				//记录已有的录音机，以便环境变化时发出通知
				static LK::Collection::DefaultArray<Recorder*> recorderList;
				//添加扬声器指针，方便有事件发生时进行通知
				static void AddSpeaker(Speaker* speaker);
				//添加录音机指针，方便有事件发生时进行通知
				static void AddRecorder(Recorder* recorder);
				//移除扬声器指针
				static void RemoveSpeaker(Speaker* speaker);
				//移除录音机指针
				static void RemoveRecorder(Recorder* recorder);
				//获取默认录音设备,使用完毕需要调用其成员函数Release()
				static IMMDevice* GetDefaultRecordingDevice();
				//获取默认播放设备,使用完毕需要调用其成员函数Release()
				static IMMDevice* GetDefaultSpeakingDevice();
				//获取按设备Id指定的设备,使用完毕需要调用其成员函数Release()
				static IMMDevice* GetDevice(const ptr<String>& Id);
				//获取设备ID
				static ptr<String> GetDeviceID(IMMDevice* pDevice);
				//根据设备名
				static ptr<String> GetDeviceName(IMMDevice* pDevice);

				//设备变更次数
				static volatile long changedCount;
			public:
#ifdef LK_FUNCTIONAL_ACTION_
				//发生各项事件时执行的委托（事件）
				static LK::Functional::PDelegate<void( ptr<String>)> OnDeviceAdded;
				static LK::Functional::PDelegate<void( ptr<String>, DWORD)> OnDeviceStateChanged;
				static LK::Functional::PDelegate<void( ptr<String>)> OnDeviceRemoved;
				static LK::Functional::PDelegate<void( EDataFlow, ERole, ptr<String>)> OnDefaultDeviceChanged;
				static LK::Functional::PDelegate<void( ptr<String>, const PROPERTYKEY)> OnPropertyValueChanged;
#endif
				//录音设备名称列表
				static const LK::Collection::DefaultArray<ptr<String>> RecordingDevicesList;
				//录音设备ID列表
				static const LK::Collection::DefaultArray<ptr<String>> RecordingDevicesIDList;
				//播放设备名称列表
				static const LK::Collection::DefaultArray< ptr<String>> SpeakingDevicesList;
				//播放设备ID列表
				static const LK::Collection::DefaultArray<ptr<String>> SpeakingDevicesIDList;

				//默认PSpeaker缓冲时间
				static ptr<Time> DefaultSpeakerRequestedDuration;
				//最小PSpeaker缓冲时间
				static ptr<Time> MinimumSpeakerRequestedDuration;
				//默认PRecorder缓冲时间
				static ptr<Time> DefaultRecorderRequestedDuration;
				//最小PRecorder缓冲时间
				static ptr<Time> MinimumRecorderRequestedDuration;
				//最后一次更改时已添加的设备ID
				static ptr<String> OnAddedDeviceId;
				//最后一次状态更改的设备ID
				static ptr<String> OnStateChangedDeviceId;
				//最后一次状态更改到的新状态
				static DWORD OnStateChangedNewState;
				//最后一次移除的设备ID
				static ptr<String> OnRemovedDeviceId;
				//最后一次默认设备更改的设备ID
				static ptr<String> OnDefaultChangedDeviceId;
				//最后一次默认设备更改的设备流向
				static EDataFlow OnDefaultChangedFlow;
				//最后一次默认设备更改的设备角色
				static ERole OnDefaultChangedRole;
				//最后一次设备属性更改的设备ID
				static ptr<String> OnPropertyValueChangedDeviceId;
				//最后一次设备属性更改的设备属性 
				static PROPERTYKEY OnPropertyValueChangedKey;
				SoundEnvironment();
				~SoundEnvironment();
				/**
				@brief 获取已有的扬声器列表*/
				static ptr<LK::Collection::IArray<PSpeaker>> GetSpeakersList();
				/**
				@brief 获取已有的录音机列表*/
				static ptr<LK::Collection::IArray<PRecorder>> GetRecordersList();
				/**
				@brief 获取更改次数*/
				static index_t GetChangedCount();
				/**
				@brief 删除原有信息*/
				static void Clear();
				/**
				@brief 刷新设备信息*/
				static void Refresh();
				static HRESULT SetState(HRESULT hr);
				/**
				@brief 获取默认录音设备Id*/
				static ptr<String> GetDefaultRecordingDeviceId();
				/**
				@brief 获取默认播放设备Id*/
				static ptr<String> GetDefaultSpeakingDeviceId();
				/**
				@brief 获取设备数量*/
				static index_t GetDevicesCount();
				/**
				@brief 根据设备名称获取id，请慎用此功能，因为可能存在相同名称的设备*/
				static ptr<String> GetDeviceID(const ptr<String>& name);
				/**
				@brief 根据设备ID获取名称，该ID既可以是录音设备也可以是播放设备的*/
				static ptr<String> GetDeviceName(const ptr<String>& id);

				static SoundEnvironment& GetDefaultRef();
			};
		}
	}
}
#endif